package br.com.massai.model.beans;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;

import br.com.massai.model.business.CollaboratorBusiness;
import br.com.massai.model.dao.ActionRepository;
import br.com.massai.model.dao.FunctionRepository;
import br.com.massai.model.dao.ModuleRepository;
import br.com.massai.model.entity.Action;
import br.com.massai.model.entity.Collaborator;
import br.com.massai.model.entity.Function;
import br.com.massai.model.entity.Module;
import br.com.massai.model.exceptions.ErrorCore;
import br.com.massai.model.exceptions.MessageCore;
import br.com.massai.model.exceptions.SystemException;
import br.com.massai.view.enums.Role;
import br.com.massai.view.utils.FacesUtil;

@ManagedBean
@ViewScoped
public class PermissionBean extends GenericBean<Collaborator> {

	private static final long serialVersionUID = -8485541058202690037L;

	private Collaborator user;
	private boolean administrator;
	private TreeNode treeRoot;

	private TreeNode[] nodesSelectedTrees;

	@EJB private CollaboratorBusiness collaboratorBusiness;
	@EJB private FunctionRepository functionRepository;
	@EJB private ActionRepository actionRepository;
	@EJB private ModuleRepository moduleRepository;

	public PermissionBean() {
		this.user = new Collaborator();
		this.administrator = false;
	}
	
	@PostConstruct
	public void loadFunctions() throws SystemException {
		loadTreeNode();
	}

	public void loadTreeNode() throws SystemException {
		List<Module> modules = moduleRepository.findAll();

		this.treeRoot = new DefaultTreeNode("Root", null);
		for(Module m : modules){
			m.setFunctions(functionRepository.findByModule(m));
			TreeNode tree = new DefaultTreeNode(m.getNameModule(), this.treeRoot);
			tree.setExpanded(true);
			if(m.getFunctions() != null && !m.getFunctions().isEmpty()){
				loadTreeNodeChild(m, tree);
			}
		}
	}

	public void loadTreeNodeChild(Module module, TreeNode parent) throws SystemException {
		TreeNode tree = null;
		for(Function f : module.getFunctions()){
			tree = new DefaultTreeNode(f.getDescription(), parent);
			loadTreeNodeAction(f, tree);
		}
	}

	public void loadTreeNodeAction(Function function, TreeNode parent) throws SystemException {
		TreeNode tree = null;
		function.setActions(actionRepository.getActionsByFunction(function));

		for(Action a : function.getActions()){
			tree = new DefaultTreeNode("document", a, parent);
			if(this.user != null && this.user.getId() != null)
				for(Action a2 : this.user.getActions()){
					if(a.equals(a2))
						tree.setSelected(true);
				}
		}
	}

	@Override
	protected Collaborator getEntity() {
		return this.user;
	}

	@Override
	public String save() throws SystemException {
		includePermissions();
		collaboratorBusiness.save(this.user);

		FacesUtil.registrarMensagem(MessageCore.SUCESS_UPDATE.getCode());
		loadTreeNode();
		return null;
	}

	public void includePermissions() throws SystemException {
		if(this.user == null || this.user.getId() == null)
			throw new SystemException(ErrorCore.ERROR_UNEXPECTED);

		if(this.administrator)
			this.user.setRole(Role.A);
		else
			this.user.setRole(Role.C);

		this.user.getActions().clear();
		if(nodesSelectedTrees != null && nodesSelectedTrees.length > 0)
			for(TreeNode t : nodesSelectedTrees)
				if(t.getData() instanceof Action)
					this.user.getActions().add((Action) t.getData());
	}

	@Override
	public void delete(Collaborator entity) throws SystemException {
		return;
	}

	@Override
	public void setParam(String param) throws SystemException {
		try{
			this.param = param;
			if(param != null && !param.isEmpty()){
				this.user = collaboratorBusiness.findID(Long.valueOf(param));
				if(this.user.getRole().equals(Role.C))
					loadTreeNode();
				else
					this.administrator = true;
			}

		} catch (NumberFormatException e) {
			throw new SystemException(ErrorCore.ERROR_ILLEGAL_ARGUMENT, e);
		} catch (IllegalArgumentException e) {
			throw new SystemException(ErrorCore.ERROR_ILLEGAL_ARGUMENT, e);
		} catch (Exception e) {
			throw new SystemException(ErrorCore.ERROR_UNEXPECTED, e);
		}
	}

	public Collaborator getUser() {
		return user;
	}

	public void setUser(Collaborator user) {
		this.user = user;
	}

	public boolean isAdministrator() {
		return administrator;
	}

	public void setAdministrator(boolean administrator) {
		this.administrator = administrator;
	}

	public TreeNode getTreeRoot() {
		return treeRoot;
	}

	public void setTreeRoot(TreeNode treeRoot) {
		this.treeRoot = treeRoot;
	}

	public TreeNode[] getNodesSelectedTrees() {
		return nodesSelectedTrees;
	}

	public void setNodesSelectedTrees(TreeNode[] nodesSelectedTrees) {
		this.nodesSelectedTrees = nodesSelectedTrees;
	}
}